package edu.dhbw.mannheim;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Text;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

@SuppressWarnings("serial")
public class Comment extends HttpServlet {
	/**
	 * every AJAX request concerning Comments
	 */
	public void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws IOException {
		String type = "";
		if (req.getParameter("type") != null)
			type = req.getParameter("type");
		if (type.equals("delete")) {
			if (Admin.isAdmin(req.getRemoteUser())) {
				DatastoreService datastore = DatastoreServiceFactory
						.getDatastoreService();
				String id = req.getParameter("id");
				long idLong = Long.parseLong(id);

				// get the entity which shall be deleted
				Key blogKey = KeyFactory.createKey("blog", "blogblogblog");
				Query query = new Query("comment", blogKey).setKeysOnly();
				List<Entity> comments = datastore.prepare(query).asList(
						FetchOptions.Builder.withDefaults());
				for (Entity comment : comments) {
					if (comment.getKey().getId() == idLong) {
						// delete the entry
						datastore.delete(comment.getKey());
						break;
					}
				}

				// return the ID
				try {
					PrintWriter out = resp.getWriter();
					out.print(id);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} else {
				System.out.println("User " + req.getRemoteUser()
						+ " has got no permissions to delete a post.");
			}
		} else if (type.equals("reload")) {
			String id = req.getParameter("id");
			int blogIdInt = Integer.parseInt(id);
			String offset = req.getParameter("offset");
			int offsetInt = Integer.parseInt(offset);
			PrintWriter out = null;
			try {
				out = resp.getWriter();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			out.println(getCommentsAsHTML(blogIdInt, offsetInt, 10));
			
		} else {
			// add a comment
			
			// comment should not be empty
			if (req.getParameter("content").isEmpty()) {
				resp.setStatus(400);
				return;
			}
			// block to frequent comments in a period of time
			DatastoreService datastore = DatastoreServiceFactory
					.getDatastoreService();
			Key commentKey = KeyFactory.createKey("blog", "blogblogblog");
			Query query = new Query("comment", commentKey).addFilter("date",
					Query.FilterOperator.GREATER_THAN, new Date(new Date().getTime()-5000));
			List<Entity> comments = datastore.prepare(query).asList(FetchOptions.Builder.withDefaults());
			if(comments.size()>5) {
				resp.setStatus(400);
				return;
			}
			
			//fetch the blog
			String blogId = req.getParameter("blogIdInt");
			int blogIdInt = Integer.parseInt(blogId);
			datastore = DatastoreServiceFactory
					.getDatastoreService();
			Key blogKey = KeyFactory.createKey("blog", "blogblogblog");
			query = new Query("post", blogKey).addFilter("internalID",
					Query.FilterOperator.EQUAL, blogIdInt + "");
			Entity blog = datastore.prepare(query).asSingleEntity();
			
			// fetch user details
			UserService userService = UserServiceFactory.getUserService();
			User user = userService.getCurrentUser();

			Text content = new Text(req.getParameter("content"));
			Date date = new Date();

			Entity comment = new Entity("comment", blog.getKey());
			comment.setProperty("user", user);
			comment.setProperty("date", date);
			comment.setProperty("content", content);

			datastore.put(comment);
			
			//return content of comment
			Comment.writeComment(comment,req,resp);
		}
	}
	
	/**
	 * transforms a list of entities to HTML tags
	 * @param comments
	 * @return
	 */
	public static String commentEntitiesToHTML(List<Entity> comments) {
		String output="";
		for(Entity c: comments) {
			output+=Comment.commentEntityToHTML(c);
		}
		return output;
	}
	
	/**
	 * transforms a comment entity to HTML tags
	 * @param comments
	 * @return
	 */
	public static String commentEntityToHTML(Entity c) {
		String output = "";
		output+="<div id=\"comment"+c.getKey().getId()+"\" class=\"small inner round\">";
		
		//Header with name
		output+=NameDate.getNameDateHTML(c);

		//Content with Delete
		output+="<table class=\"fullwidth\"><tr>";
			output+="<td>";
				output+="<blockquote>";
					output+=((Text)c.getProperty("content")).getValue();
				output+="</blockquote>";
			output+="</td>";
			UserService userService = UserServiceFactory.getUserService();
			User user = userService.getCurrentUser(); 
			if(user !=null && Admin.isAdmin(user.getEmail())) {
				output+="<td class=\"right\">";
					output+="<a href='javascript:deleteComment("+c.getKey().getId()+")'>X</a>";
				output+="</td>";
			}
			output+="</tr></table>";
		output+="</div>";
		return output;
	}
	
	/**
	 * get comments
	 * @param blogID the blog the comments belong to
	 * @param offset the offset (started at the newest) at which the comments shall begin
	 * @param amount the amount of comments which shall be returned
	 * @return HTML string
	 */
	public static String getCommentsAsHTML(int blogID, int offset, int amount) {
		//get the blog
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		Key blogKey = KeyFactory.createKey("blog", "blogblogblog");
		Query query = new Query("post", blogKey).addFilter("internalID", Query.FilterOperator.EQUAL, blogID+"");
		Entity blog = datastore.prepare(query).asSingleEntity();
		
		if(blog!=null) {
			Query blogComments = new Query("comment").addSort("date",Query.SortDirection.DESCENDING);
			blogComments.setAncestor(blog.getKey());
			List<Entity> comments = datastore.prepare(blogComments).asList(FetchOptions.Builder.withLimit(amount).offset(offset));
			return Comment.commentEntitiesToHTML(comments);
		}
		return "";
	}
	
	/**
	 * writes a comment entity to the response output stream
	 */
	public static void writeComment(Entity c, HttpServletRequest req, HttpServletResponse resp) {
		PrintWriter out = null;
		try {
			out = resp.getWriter();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		out.println(commentEntityToHTML(c));
	}

}
